package org.googlecode.openapi_java.async;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.Callable;

import org.googlecode.openapi_java.Album;
import org.googlecode.openapi_java.AlbumWithThumb;
import org.googlecode.openapi_java.Group;
import org.googlecode.openapi_java.Message;
import org.googlecode.openapi_java.OpenApi;
import org.googlecode.openapi_java.Photo;
import org.googlecode.openapi_java.Profile;
import org.googlecode.openapi_java.ProfiledContainer;
import org.googlecode.openapi_java.Status;
import org.googlecode.openapi_java.VkontakteException;


public class AsyncApi {

	public interface Processor<D, R> {
		public R process(D data);
	}

	private OpenApi api;

	public AsyncApi(OpenApi api) {
		this.api = api;
	}

	public <T> Callable<T> deleteStatus(final long statusId,
			final Processor<Boolean, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.deleteStatus(statusId));
			}
		};
	}

	public <T> Callable<T> getAlbums(final Processor<List<Album>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getAlbums());
			}
		};
	}

	public <T> Callable<T> getAlbums(final List<Long> albumIds,
			final Processor<List<Album>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getAlbums(albumIds));
			}
		};
	}
	
	public <T> Callable<T> getAlbums(final Long userId,
			final Processor<List<Album>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getAlbums(userId));
			}
		};
	}

	public <T> Callable<T> getAlbums(final Long userId,
			final List<Long> albumIds, final Processor<List<Album>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getAlbums(userId, albumIds));
			}
		};
	}

	
	public <T> Callable<T> getAlbumsWithThumb(final Long userId,
			final Processor<List<AlbumWithThumb>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getAlbumsWithThumb(userId));
			}
		};
	}
	
	
	public <T> Callable<T> getFriends(final Long uid,
			final Processor<List<Profile>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getFriends(uid));
			}
		};
	}
	
	public <T> Callable<T> getGroups(final Processor<List<Group>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getGroups());
			}
		};
	}

	public <T> Callable<T> getGroupsIds(final Processor<List<Long>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getGroupsIds());
			}
		};
	}

	public <T> Callable<T> getPhotos(final long userId, final long albumId,
			final Processor<List<Photo>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getPhotos(userId, albumId));
			}
		};
	}

	public <T> Callable<T> getPhotos(final long userId, final long albumId,
			final List<Long> photosIds,
			final Processor<List<Photo>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getPhotos(userId, albumId,
						photosIds));
			}
		};
	}
	
	public <T> Callable<T> getPhotosById(final List<String> photoIds,final Processor<List<Photo>, T> processor){
		
		return new Callable<T>() {

			public T call() throws Exception {
				T t =  processor.process(api.getPhotosById(photoIds));
				return t;
			}
		};
	}
	
	
	public <T> Callable<T> getProfiles(final List<Long> uids,final Processor<List<Profile>, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getProfiles(uids));
			}
		};
	}
	
	public <T> Callable<T> getProfiles(final List<Long> uids,final List<String> fields ,final Processor<List<Profile>, T> processor){
		return new Callable<T>() {
			public T call() throws Exception {
				return processor.process(api.getProfiles(uids, fields));
			}
		};
	}

	public <T> Callable<T> getProfilesWithAllData(final List<Long> uids,final Processor<List<Profile>, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getProfilesWithAllData(uids));
			}
		};
	}
	

	public <T> Callable<T> getStatus(final Processor<Status, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getStatus());
			}
		};
	}
	
	public <T> Callable<T> getStatusHistory(final Processor<List<Status>, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getStatusHistory());
			}
		};
	}
	
	public <T> Callable<T> getStatusHistory(final long uid, final Processor<List<Status>, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getStatusHistory(uid));
			}
		};
	}

	
	
	public <T> Callable<T> getStatusNews(final long timestamp,
			final Processor<List<Status>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getStatusNews(timestamp));

			}
		};
	}

	public <T> Callable<T> getStatusNews(final int offset, final int count,
			final Processor<List<Status>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getStatusNews(offset, count));

			}
		};
	}

	public <T> Callable<T> getStatusNews(
			final Processor<List<Status>, T> processor) {
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.getStatusNews());

			}
		};
	}
	
	
	public <T> Callable<T> getNewsWithProfile(final long timestamp,
			final Processor<List<ProfiledContainer<Status>>, T> processor) {
		return new Callable<T>() {
			public T call() throws Exception {
				return processor.process(api.getNewsWithProfile(timestamp));
			}
		};
	}


	public <T> Callable<T> setStatus(final String status, final Processor<Long, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return processor.process(api.setStatus(status));
			}
		};
	}

	
	public <T> Callable<T> getFullIncomeMessages(final Processor<List<Message>, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return  processor.process(api.getFullIncomeMessages());
			}
		};
	}

	public <T> Callable<T> getFullIncomeMessagesWithProfile(final Processor<List<ProfiledContainer<Message>>, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return  processor.process(api.getFullIncomeMessagesWithProfile());
			}
		};
	}
	
	
	
	public <T> Callable<T> getFullOutcomeMessages(final Processor<List<Message>, T> processor){
		return new Callable<T>() {

			public T call() throws Exception {
				return  processor.process(api.getFullOutcomeMessages());
			}
		};
	}
	
	
	
	// /

	private class IdentityFunction<D> implements Processor<D, D> {
		public D process(D data) {
			return data;
		}
	}
	
	
	public Callable<Boolean> deleteStatus(long statusId) {
		return deleteStatus(statusId,new IdentityFunction<Boolean>());
	}

	public Callable<List<Album>> getAlbums() {
		return getAlbums(new IdentityFunction<List<Album>>());
	}
	
	public Callable<List<Album>> getAlbums(List<Long> albumsIds) {
		return getAlbums(albumsIds, new IdentityFunction<List<Album>>());
	}

	public Callable<List<Album>> getAlbums(long uid) {
		return getAlbums(uid, new IdentityFunction<List<Album>>());
	}
	
	public Callable<List<Album>> getAlbums(long uid, List<Long> albumsIds) {
		return getAlbums(uid, albumsIds, new IdentityFunction<List<Album>>());
	}
	
	
	
	public Callable<List<Group>> getGroups() {
		return getGroups(new IdentityFunction<List<Group>>());
	}
	
	public Callable<List<Long>> getGroupsIds() {
		return getGroupsIds(new IdentityFunction<List<Long>>());
	}
	
	public Callable<List<Photo>> getPhotos(long userId, long albumId) {
		return getPhotos(userId, albumId, new IdentityFunction<List<Photo>>());
	}
	
	public Callable<List<Photo>> getPhotos(long userId, long albumId, List<Long> photosIds) {
		return getPhotos(userId, albumId, photosIds, new IdentityFunction<List<Photo>>());
	}
	
	public Callable<List<Photo>> getPhotosById(List<String> photosIds) {
		return getPhotosById(photosIds, new IdentityFunction<List<Photo>>());
	}

	public Callable<List<Profile>> getProfiles(List<Long> uids) {
		return getProfiles(uids, new IdentityFunction<List<Profile>>());
	}
	
	public Callable<Status> getStatus() {
		return getStatus(new IdentityFunction<Status>());
	}
	
	public Callable<List<Status>> getStatusHistory() {
		return getStatusHistory(new IdentityFunction<List<Status>>());
	}

	public Callable<List<Status>> getStatusHistory(long uid) {
		return getStatusHistory(uid, new IdentityFunction<List<Status>>());
	}

	
	public Callable<List<Status>> getStatusNews() {
		return getStatusNews(new IdentityFunction<List<Status>>());
	}

	public Callable<List<Status>> getStatusNews(long timestamp) {
		return getStatusNews(timestamp, new IdentityFunction<List<Status>>());
	}

	public Callable<List<Status>> getStatusNews(int offset, int count) {
		return getStatusNews(offset, count,
				new IdentityFunction<List<Status>>());
	}

	public Callable<Long> setStatus(String status) {
		return setStatus(status, new IdentityFunction<Long>());
	}

	public Callable<List<Message>> getFullIncomeMessages(){
		return getFullIncomeMessages(new IdentityFunction<List<Message>>());
		
	}
	
	public Callable<List<Message>> getFullOutcomeMessages(){
		return getFullOutcomeMessages(new IdentityFunction<List<Message>>());
		
	}
	
}
